//! Epic 9: 彩色控制台输出 - ATDD 验收测试
//!
//! 本测试文件遵循 ATDD (验收测试驱动开发) 方法论：
//! - 测试在实现前编写，初始状态为 RED (失败)
//! - 实现代码后测试变为 GREEN (通过)
//! - 重构时测试提供安全网
//!
//! 测试覆盖:
//! - AC-9.1: 彩色格式化器基础功能
//! - AC-9.2: 彩色开关配置
//! - AC-9.3: 终端颜色自动检测
//! - AC-9.4: Feature Flag 控制

#![cfg(feature = "color")]

use log4r::{Formatter, Level, LogEvent};
use std::io::IsTerminal;

mod common;

// =============================================================================
// AC-9.1: 彩色格式化器基础功能
// =============================================================================

mod colorize_level_tests {
    use super::*;

    /// P0: TRACE 级别应输出灰色 (bright_black)
    ///
    /// GIVEN: ColoredFormatter 已启用
    /// WHEN: 格式化 TRACE 级别日志
    /// THEN: 输出包含 bright_black ANSI 转义码
    #[test]
    fn test_trace_level_outputs_gray() {
        // GIVEN: 启用彩色的格式化器
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN: 格式化 TRACE 级别事件
        let event = LogEvent::new(Level::Trace, "test::module", "trace message");
        let output = formatter.format(&event);

        // THEN: 输出包含 bright_black ANSI 转义码 (\x1b[90m)
        assert!(
            output.contains("\x1b[90m") || output.contains("\x1b[38;5;8m"),
            "TRACE 级别应使用灰色 (bright_black)，实际输出: {}",
            output
        );
    }

    /// P0: DEBUG 级别应输出蓝色
    ///
    /// GIVEN: ColoredFormatter 已启用
    /// WHEN: 格式化 DEBUG 级别日志
    /// THEN: 输出包含 blue ANSI 转义码
    #[test]
    fn test_debug_level_outputs_blue() {
        // GIVEN
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN
        let event = LogEvent::new(Level::Debug, "test::module", "debug message");
        let output = formatter.format(&event);

        // THEN: 蓝色 ANSI 转义码 (\x1b[34m)
        assert!(
            output.contains("\x1b[34m"),
            "DEBUG 级别应使用蓝色，实际输出: {}",
            output
        );
    }

    /// P0: INFO 级别应输出绿色
    ///
    /// GIVEN: ColoredFormatter 已启用
    /// WHEN: 格式化 INFO 级别日志
    /// THEN: 输出包含 green ANSI 转义码
    #[test]
    fn test_info_level_outputs_green() {
        // GIVEN
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN
        let event = LogEvent::new(Level::Info, "test::module", "info message");
        let output = formatter.format(&event);

        // THEN: 绿色 ANSI 转义码 (\x1b[32m)
        assert!(
            output.contains("\x1b[32m"),
            "INFO 级别应使用绿色，实际输出: {}",
            output
        );
    }

    /// P0: WARN 级别应输出黄色
    ///
    /// GIVEN: ColoredFormatter 已启用
    /// WHEN: 格式化 WARN 级别日志
    /// THEN: 输出包含 yellow ANSI 转义码
    #[test]
    fn test_warn_level_outputs_yellow() {
        // GIVEN
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN
        let event = LogEvent::new(Level::Warn, "test::module", "warn message");
        let output = formatter.format(&event);

        // THEN: 黄色 ANSI 转义码 (\x1b[33m)
        assert!(
            output.contains("\x1b[33m"),
            "WARN 级别应使用黄色，实际输出: {}",
            output
        );
    }

    /// P0: ERROR 级别应输出红色
    ///
    /// GIVEN: ColoredFormatter 已启用
    /// WHEN: 格式化 ERROR 级别日志
    /// THEN: 输出包含 red ANSI 转义码
    #[test]
    fn test_error_level_outputs_red() {
        // GIVEN
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN
        let event = LogEvent::new(Level::Error, "test::module", "error message");
        let output = formatter.format(&event);

        // THEN: 红色 ANSI 转义码 (\x1b[31m)
        assert!(
            output.contains("\x1b[31m"),
            "ERROR 级别应使用红色，实际输出: {}",
            output
        );
    }

    /// P0: FATAL 级别应输出红色加粗
    ///
    /// GIVEN: ColoredFormatter 已启用
    /// WHEN: 格式化 FATAL 级别日志
    /// THEN: 输出包含 red + bold ANSI 转义码
    #[test]
    fn test_fatal_level_outputs_red_bold() {
        // GIVEN
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN
        let event = LogEvent::new(Level::Fatal, "test::module", "fatal message");
        let output = formatter.format(&event);

        // THEN: 红色 (\x1b[31m) 和 粗体 (\x1b[1m)
        assert!(
            output.contains("\x1b[31m") && output.contains("\x1b[1m"),
            "FATAL 级别应使用红色加粗，实际输出: {}",
            output
        );
    }
}

// =============================================================================
// AC-9.1: 时间戳和模块路径颜色
// =============================================================================

mod timestamp_and_target_color_tests {
    use super::*;

    /// P1: 时间戳应使用暗灰色
    ///
    /// GIVEN: ColoredFormatter 已启用
    /// WHEN: 格式化日志事件
    /// THEN: 时间戳部分使用 bright_black 颜色
    #[test]
    fn test_timestamp_uses_dark_gray() {
        // GIVEN
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN
        let event = LogEvent::new(Level::Info, "test::module", "message");
        let output = formatter.format(&event);

        // THEN: 时间戳应在 bright_black 颜色区域内
        // 时间戳格式: YYYY-MM-DD HH:MM:SS.mmm
        // 应该被 \x1b[90m ... \x1b[0m 包围
        assert!(
            output.contains("\x1b[90m") || output.contains("\x1b[38;5;8m"),
            "时间戳应使用暗灰色，实际输出: {}",
            output
        );
    }

    /// P1: 模块路径应使用青色
    ///
    /// GIVEN: ColoredFormatter 已启用
    /// WHEN: 格式化日志事件
    /// THEN: 模块路径 (target) 使用 cyan 颜色
    #[test]
    fn test_target_uses_cyan() {
        // GIVEN
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN
        let event = LogEvent::new(Level::Info, "my_app::database", "message");
        let output = formatter.format(&event);

        // THEN: 青色 ANSI 转义码 (\x1b[36m)
        assert!(
            output.contains("\x1b[36m"),
            "模块路径应使用青色，实际输出: {}",
            output
        );
        // 并且包含模块路径文本
        assert!(output.contains("my_app::database"), "输出应包含模块路径");
    }
}

// =============================================================================
// AC-9.2: 彩色开关配置
// =============================================================================

mod color_config_tests {
    use super::*;

    /// P0: NO_COLOR=1 环境变量应禁用颜色
    ///
    /// GIVEN: NO_COLOR 环境变量已设置
    /// WHEN: 调用 should_colorize()
    /// THEN: 返回 false，禁用颜色
    #[test]
    fn test_no_color_env_disables_color() {
        // GIVEN: 设置 NO_COLOR 环境变量
        std::env::set_var("NO_COLOR", "1");

        // WHEN
        let result = log4r::formatter::should_colorize(true);

        // THEN
        assert!(!result, "NO_COLOR=1 时应禁用颜色");

        // 清理
        std::env::remove_var("NO_COLOR");
    }

    /// P0: NO_COLOR 未设置时应启用颜色 (如果配置启用)
    ///
    /// GIVEN: NO_COLOR 环境变量未设置，配置启用颜色
    /// WHEN: 调用 should_colorize()
    /// THEN: 返回 true (假设是 TTY)
    #[test]
    fn test_no_color_unset_enables_color() {
        // GIVEN: 确保 NO_COLOR 未设置
        std::env::remove_var("NO_COLOR");

        // WHEN: 配置启用颜色
        // 注意: 在 CI 环境中 is_terminal() 可能返回 false
        // 这个测试主要验证 NO_COLOR 逻辑
        let result = log4r::formatter::should_colorize(true);

        // THEN: 如果是 TTY，应返回 true
        // 在 CI 中可能返回 false (非 TTY)，这是预期行为
        // 我们只验证函数不会 panic
        let _ = result;
    }

    /// P1: colored=false 配置应禁用颜色
    ///
    /// GIVEN: 配置 colored = false
    /// WHEN: 创建 ColoredFormatter
    /// THEN: 输出不包含 ANSI 转义码
    #[test]
    fn test_config_disabled_no_ansi_codes() {
        // GIVEN: 禁用彩色的格式化器
        let formatter = log4r::formatter::ColoredFormatter::new(false);

        // WHEN
        let event = LogEvent::new(Level::Info, "test::module", "message");
        let output = formatter.format(&event);

        // THEN: 不包含 ANSI 转义码
        assert!(
            !output.contains("\x1b["),
            "colored=false 时不应包含 ANSI 转义码，实际输出: {}",
            output
        );
    }

    /// P1: colored=true 配置应启用颜色
    ///
    /// GIVEN: 配置 colored = true
    /// WHEN: 创建 ColoredFormatter
    /// THEN: 输出包含 ANSI 转义码
    #[test]
    fn test_config_enabled_has_ansi_codes() {
        // GIVEN: 启用彩色的格式化器
        let formatter = log4r::formatter::ColoredFormatter::new(true);

        // WHEN
        let event = LogEvent::new(Level::Info, "test::module", "message");
        let output = formatter.format(&event);

        // THEN: 包含 ANSI 转义码
        assert!(
            output.contains("\x1b["),
            "colored=true 时应包含 ANSI 转义码，实际输出: {}",
            output
        );
    }

    /// P1: TERM=dumb 应禁用颜色
    ///
    /// GIVEN: TERM 环境变量设置为 "dumb"
    /// WHEN: 调用 should_colorize()
    /// THEN: 返回 false
    #[test]
    fn test_term_dumb_disables_color() {
        // GIVEN
        std::env::set_var("TERM", "dumb");
        std::env::remove_var("NO_COLOR");

        // WHEN
        let result = log4r::formatter::should_colorize(true);

        // THEN
        assert!(!result, "TERM=dumb 时应禁用颜色");

        // 清理
        std::env::remove_var("TERM");
    }
}

// =============================================================================
// AC-9.3: 终端颜色自动检测 (IsTerminal)
// =============================================================================

mod is_terminal_tests {
    #[allow(unused_imports)]
    use super::*;

    /// P1: 配置禁用应覆盖终端检测
    ///
    /// GIVEN: 配置 enabled = false
    /// WHEN: 调用 should_colorize()
    /// THEN: 返回 false，无论终端状态如何
    #[test]
    fn test_config_disabled_overrides_terminal() {
        // GIVEN: 配置禁用
        std::env::remove_var("NO_COLOR");
        std::env::remove_var("TERM");

        // WHEN
        let result = log4r::formatter::should_colorize(false);

        // THEN: 配置禁用优先
        assert!(!result, "配置禁用时应返回 false");
    }

    /// P1: should_colorize 应检测 stdout 是否为 TTY
    ///
    /// GIVEN: 标准环境
    /// WHEN: 调用 should_colorize()
    /// THEN: 结果取决于 stdout.is_terminal()
    #[test]
    fn test_should_colorize_checks_terminal() {
        // GIVEN: 清理环境变量
        std::env::remove_var("NO_COLOR");
        std::env::remove_var("TERM");

        // WHEN
        let result = log4r::formatter::should_colorize(true);

        // THEN: 在 CI 中通常是 false (非 TTY)
        // 在本地终端中通常是 true
        // 我们只验证函数正常工作
        println!("should_colorize(true) = {}", result);
        println!("stdout.is_terminal() = {}", std::io::stdout().is_terminal());
    }

    /// P1: 管道输出时应自动禁用颜色
    ///
    /// 注意: 这个测试在 CI 环境中自动验证，因为 CI 通常不是 TTY
    #[test]
    fn test_pipe_output_disables_color() {
        // GIVEN: 检查当前 stdout 状态
        let is_tty = std::io::stdout().is_terminal();

        // WHEN: 在非 TTY 环境中
        if !is_tty {
            std::env::remove_var("NO_COLOR");
            std::env::remove_var("TERM");

            let result = log4r::formatter::should_colorize(true);

            // THEN: 应禁用颜色
            assert!(!result, "非 TTY 环境应禁用颜色");
        } else {
            // 在 TTY 环境中跳过此测试
            println!("跳过: 当前是 TTY 环境");
        }
    }
}

// =============================================================================
// AC-9.3.5: 检测结果缓存测试
// =============================================================================

mod cache_tests {
    /// IT-9.3-001: cached_terminal_color_support 函数可从 lib 导出访问
    #[test]
    fn test_cached_terminal_color_support_exported() {
        // GIVEN/WHEN: 从 log4r 导入并调用
        let result = log4r::cached_terminal_color_support();

        // THEN: 应返回布尔值
        let _ = result;
    }

    /// IT-9.3-002: 缓存结果多次调用一致
    #[test]
    fn test_cached_result_consistent() {
        // GIVEN: 首次调用
        let first = log4r::cached_terminal_color_support();

        // WHEN: 多次调用
        let second = log4r::cached_terminal_color_support();
        let third = log4r::cached_terminal_color_support();

        // THEN: 结果应一致
        assert_eq!(first, second, "缓存结果应一致");
        assert_eq!(second, third, "缓存结果应一致");
    }

    /// IT-9.3-003: 缓存线程安全
    #[test]
    fn test_cache_thread_safe() {
        use std::sync::Arc;
        use std::thread;

        // GIVEN: 多线程环境
        let results = Arc::new(std::sync::Mutex::new(Vec::new()));
        let mut handles = vec![];

        // WHEN: 多线程并发调用
        for _ in 0..4 {
            let results_clone = Arc::clone(&results);
            let handle = thread::spawn(move || {
                for _ in 0..10 {
                    let result = log4r::cached_terminal_color_support();
                    results_clone.lock().unwrap().push(result);
                }
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.join().unwrap();
        }

        // THEN: 所有结果应一致
        let results = results.lock().unwrap();
        let first = results[0];
        for result in results.iter() {
            assert_eq!(*result, first, "多线程调用结果应一致");
        }
    }

    /// IT-9.3-004: should_colorize 与 cached_terminal_color_support 结果一致（配置启用时）
    #[test]
    fn test_should_colorize_matches_cached() {
        // GIVEN: 清理环境变量
        std::env::remove_var("NO_COLOR");
        std::env::remove_var("TERM");

        // WHEN: 调用两个函数
        let cached = log4r::cached_terminal_color_support();
        let should = log4r::should_colorize(true);

        // THEN: 结果应一致（因为 should_colorize(true) 内部使用缓存）
        assert_eq!(cached, should, "should_colorize(true) 应使用缓存结果");
    }
}

// =============================================================================
// AC-9.4: Formatter Trait 兼容性
// =============================================================================

mod formatter_trait_tests {
    use super::*;

    /// P2: ColoredFormatter 应实现 Formatter trait
    ///
    /// GIVEN: ColoredFormatter 实例
    /// WHEN: 作为 Formatter trait 对象使用
    /// THEN: 可以正常调用 format() 方法
    #[test]
    fn test_colored_formatter_implements_trait() {
        // GIVEN
        let formatter: Box<dyn Formatter> = Box::new(log4r::formatter::ColoredFormatter::new(true));

        // WHEN
        let event = LogEvent::new(Level::Info, "test", "message");
        let output = formatter.format(&event);

        // THEN: 输出非空
        assert!(!output.is_empty(), "格式化输出不应为空");
    }

    /// P2: ColoredFormatter 输出格式应与 TextFormatter 一致 (禁用颜色时)
    ///
    /// GIVEN: ColoredFormatter(enabled=false) 和 TextFormatter
    /// WHEN: 格式化相同事件
    /// THEN: 输出格式相同 (除了可能的空白差异)
    #[test]
    fn test_colored_formatter_matches_text_formatter_when_disabled() {
        // GIVEN
        let colored = log4r::formatter::ColoredFormatter::new(false);
        let text = log4r::formatter::TextFormatter::new();

        // WHEN
        let event = LogEvent::new(Level::Info, "test::module", "test message");
        let colored_output = colored.format(&event);
        let _text_output = text.format(&event);

        // THEN: 格式应相同
        // 注意: 可能有细微差异，主要验证结构一致
        assert!(colored_output.contains("INFO"), "应包含级别");
        assert!(colored_output.contains("test::module"), "应包含模块路径");
        assert!(colored_output.contains("test message"), "应包含消息");
    }
}

// =============================================================================
// Story 9.2: 配置文件彩色开关测试
// =============================================================================

mod config_file_colored_tests {
    use log4r::config::{ConsoleConfig, ConsoleTarget, Log4rConfig};

    /// UT-9.2-IT-001: 配置文件 colored = false 时禁用彩色 (AC-9.2.1)
    ///
    /// GIVEN: 配置文件设置 colored = false
    /// WHEN: 解析配置
    /// THEN: ConsoleConfig.colored 为 false
    #[test]
    fn test_config_colored_false_disables_color() {
        // GIVEN: 包含 colored = false 的 TOML 配置
        let toml_str = r#"
level = "info"
app_name = "test_app"

[appenders.console]
enabled = true
target = "stdout"
colored = false
"#;

        // WHEN: 解析配置
        let config: Log4rConfig = toml::from_str(toml_str).unwrap();

        // THEN: colored 应为 false
        assert!(config.appenders.console.is_some());
        let console = config.appenders.console.unwrap();
        assert!(!console.colored, "colored = false 应禁用彩色");
    }

    /// UT-9.2-IT-002: 配置文件省略 colored 时默认启用 (AC-9.2.2)
    ///
    /// GIVEN: 配置文件未设置 colored 字段
    /// WHEN: 解析配置
    /// THEN: ConsoleConfig.colored 默认为 true
    #[test]
    fn test_config_colored_default_true() {
        // GIVEN: 不包含 colored 的 TOML 配置
        let toml_str = r#"
level = "info"
app_name = "test_app"

[appenders.console]
enabled = true
target = "stdout"
"#;

        // WHEN: 解析配置
        let config: Log4rConfig = toml::from_str(toml_str).unwrap();

        // THEN: colored 应默认为 true
        assert!(config.appenders.console.is_some());
        let console = config.appenders.console.unwrap();
        assert!(console.colored, "colored 默认应为 true");
    }

    /// UT-9.2-IT-003: ConsoleConfig 默认值测试 (AC-9.2.2)
    #[test]
    fn test_console_config_default_colored() {
        // GIVEN/WHEN: 创建默认 ConsoleConfig
        let config = ConsoleConfig::default();

        // THEN: colored 应为 true
        assert!(config.colored, "ConsoleConfig 默认 colored 应为 true");
    }

    /// UT-9.2-IT-004: 配置 colored = true 显式启用 (AC-9.2.1)
    #[test]
    fn test_config_colored_true_explicit() {
        // GIVEN: 显式设置 colored = true 的 TOML 配置
        let toml_str = r#"
[appenders.console]
enabled = true
target = "stderr"
colored = true
"#;

        // WHEN: 解析配置
        let config: Log4rConfig = toml::from_str(toml_str).unwrap();

        // THEN: colored 应为 true
        let console = config.appenders.console.unwrap();
        assert!(console.colored);
        assert_eq!(console.target, ConsoleTarget::Stderr);
    }
}

// =============================================================================
// Story 9.2: Builder API 彩色开关测试
// =============================================================================

mod builder_colored_tests {
    use log4r::Log4rBuilder;

    /// UT-9.2-IT-005: Builder with_console_colored(false) 禁用彩色 (AC-9.2.5)
    #[test]
    fn test_builder_with_console_colored_false() {
        // GIVEN/WHEN: 使用 with_console_colored(false) 创建 Builder
        let builder = Log4rBuilder::new().with_console_colored(false);

        // THEN: Builder 应成功创建（验证不 panic）
        // 注意: 无法直接访问 builder.colored 字段，通过编译验证 API 存在
        let _ = builder;
    }

    /// UT-9.2-IT-006: Builder with_console_colored(true) 启用彩色 (AC-9.2.5)
    #[test]
    fn test_builder_with_console_colored_true() {
        // GIVEN/WHEN: 使用 with_console_colored(true) 创建 Builder
        let builder = Log4rBuilder::new().with_console_colored(true);

        // THEN: Builder 应成功创建
        let _ = builder;
    }

    /// UT-9.2-IT-007: Builder with_colored() 启用彩色 (向后兼容)
    #[test]
    fn test_builder_with_colored() {
        // GIVEN/WHEN: 使用 with_colored() 创建 Builder
        let builder = Log4rBuilder::new().with_colored();

        // THEN: Builder 应成功创建
        let _ = builder;
    }

    /// UT-9.2-IT-008: Builder 链式调用 with_console_colored (AC-9.2.5)
    #[test]
    fn test_builder_chain_with_console_colored() {
        // GIVEN/WHEN: 链式调用多个 Builder 方法
        let builder = Log4rBuilder::new()
            .with_level(log4r::Level::Debug)
            .with_console(log4r::ConsoleTarget::Stdout)
            .with_console_colored(false)
            .with_app_name("test_app");

        // THEN: Builder 应成功创建
        let _ = builder;
    }
}

// =============================================================================
// 边界情况测试
// =============================================================================

mod edge_case_tests {
    use super::*;

    /// P2: 空消息的彩色格式化
    #[test]
    fn test_empty_message_formatting() {
        let formatter = log4r::formatter::ColoredFormatter::new(true);
        let event = LogEvent::new(Level::Info, "test", "");
        let output = formatter.format(&event);

        // 不应 panic，输出应包含基本结构
        assert!(output.contains("INFO"));
    }

    /// P2: 包含特殊字符的消息
    #[test]
    fn test_special_characters_in_message() {
        let formatter = log4r::formatter::ColoredFormatter::new(true);
        let event = LogEvent::new(
            Level::Info,
            "test",
            "消息包含 Unicode: 你好 🎉 and ANSI: \x1b[31mred\x1b[0m",
        );
        let output = formatter.format(&event);

        // 不应 panic
        assert!(output.contains("你好"));
        assert!(output.contains("🎉"));
    }

    /// P2: 超长消息的彩色格式化
    #[test]
    fn test_long_message_formatting() {
        let formatter = log4r::formatter::ColoredFormatter::new(true);
        let long_message = "x".repeat(10000);
        let event = LogEvent::new(Level::Info, "test", long_message.clone());
        let output = formatter.format(&event);

        // 不应 panic，消息应完整
        assert!(output.contains(&long_message));
    }
}
